package com.activity;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import util.ApplicationConstant;

import com.activity.R;
import com.fragment.BookmarkRecentFragment;
import com.fragment.LocateDetailsFragment;
import com.fragment.MyLocateFragment;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.InfoWindowAdapter;
import com.google.android.gms.maps.GoogleMap.OnCameraChangeListener;
import com.google.android.gms.maps.GoogleMap.OnInfoWindowClickListener;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.PolylineOptions;

import dao.HttpPostThread;
import dao.LoadCategory;
import dao.LoadLocate;
import dao.PlaceJSONParser;
import entities.Category;
import entities.Locate;
import entities.MyLocate;
import android.R.color;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Point;
import android.location.Address;
import android.location.Criteria;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.StrictMode;
import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.app.FragmentActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.AutoCompleteTextView;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.SearchView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.SearchView.OnQueryTextListener;

@SuppressLint("NewApi")
public class MapActivity extends FragmentActivity {
	private ImageView btnSearch;
	private RadioGroup radioGroup;
	// google map api
	public static GoogleMap googleMap;
	public static Geocoder geocoder;
	// role
	public static boolean role_cal_cameraChange;
	// flag
	public static boolean mark_one;
	public static boolean callback_detail_locate = false;
	public static int postion_locate = 0;
	public static ProgressDialog progressDialog;
	private AutoCompleteTextView atvPlaces;
	private PlacesTask placesTask;
	private ParserTaskPlace parserTask;
	public static String addressNotFound;	
	@Override
	protected void onCreate(Bundle arg0) {
		// TODO Auto-generated method stub
		super.onCreate(arg0);
		setContentView(R.layout.map);
		addressNotFound=getResources().getString(R.string.address_not_found);
		atvPlaces = (AutoCompleteTextView) findViewById(R.id.atv_places);
		atvPlaces.setThreshold(1);
		
		atvPlaces.addTextChangedListener(new TextWatcher() {

			@Override
			public void onTextChanged(CharSequence s, int start, int before,
					int count) {
				placesTask = new PlacesTask();
				placesTask.execute(s.toString());
			}

			@Override
			public void beforeTextChanged(CharSequence s, int start, int count,
					int after) {
				// TODO Auto-generated method stub
			}

			@Override
			public void afterTextChanged(Editable s) {
				// TODO Auto-generated method stub
			}
		});
		// constructor------------------------
		progressDialog = new ProgressDialog(this);
		progressDialog.setCancelable(false);
		progressDialog.setMessage(getResources().getString(
				R.string.dialog_content));
		progressDialog.setIndeterminate(true);

		// find view by id-------------------------
		btnSearch=(ImageView) findViewById(R.id.button_search);
		btnSearch.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				GeocoderTask geocoderTask=new GeocoderTask();
				geocoderTask.execute(atvPlaces.getText().toString());
			}
		});
		radioGroup = (RadioGroup) findViewById(R.id.radioGroup1);
		
		// google map--------------------
		geocoder = new Geocoder(getBaseContext());
		SupportMapFragment fm = (SupportMapFragment) getSupportFragmentManager()
				.findFragmentById(R.id.map);
		googleMap = fm.getMap();
		googleMap.setMyLocationEnabled(true);
		googleMap.setOnCameraChangeListener(new OnCameraChangeListener() {

			@Override
			public void onCameraChange(CameraPosition ca) {
				// TODO Auto-generated method stub
				if (MainAppActivity.orginalLatl != null) {
					Log.d("MapActivity on my camera change", "--------------");
					Log.d("MapActivity now la:", ""
							+ MainAppActivity.orginalLatl.latitude);
					Log.d("MapActivity now log:", ""
							+ MainAppActivity.orginalLatl.longitude);
					Log.d("MapActivity my la:", "" + ca.target.latitude);
					Log.d("MapActivity my log:", "" + ca.target.longitude);
				}

			}
		});
		radioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {

			@Override
			public void onCheckedChanged(RadioGroup arg0, int id) {
				// TODO Auto-generated method stub
				if (id == R.id.radio_normal_map)
					googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
				else if (id == R.id.radio_satellite_map)
					googleMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
				else if (id == R.id.radio_terrain_map)
					googleMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
				else if (id == R.id.radio_hybrid_map)
					googleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
			}
		});
		// infor window click
		googleMap.setOnInfoWindowClickListener(new OnInfoWindowClickListener() {

			@Override
			public void onInfoWindowClick(Marker marker) {
				// TODO Auto-generated method stub
				ArrayList<Locate> list = null;
				if (ApplicationConstant.IS_CALLING_BOOKMARK == true
						|| ApplicationConstant.IS_CALLING_RECENT == true) {
					list = BookmarkRecentFragment.listLocate;
				} else {
					list = LoadLocate.listLocate;
				}

				for (int i = 0; i < list.size(); i++) {
					if (list.get(i).getDistanceFromLocation(
							marker.getPosition()) < 0.1) {
						callback_detail_locate = true;
						postion_locate = i;
						finish();
						return;
					}
				}
			}
		});
		// move den vi tri hien tai
		googleMap.moveCamera(CameraUpdateFactory
				.newLatLng(MainAppActivity.orginalLatl));
		googleMap.animateCamera(CameraUpdateFactory.zoomTo(15));
		// get intent
		// getIntent().getExtras().getString(ApplicationConstant.ACTION)
		// .equals(ApplicationConstant.MARK_ON_MAP_SOME);
		// role_cal_cameraChange = true;
		Intent intent = getIntent();
		if (intent != null) {
			String extraString = null;
			try {
				extraString = intent.getExtras().getString(
						ApplicationConstant.ACTION);
			} catch (Exception ex) {

			}

			if (extraString != null) {
				Log.d("extraStringdfsdfsd", extraString);
				if (extraString.equals(ApplicationConstant.MARK_ON_MAP_SOME)) {
					Log.d("da goi mark on map some", "------------------------");
					role_cal_cameraChange = true;
				} else if (extraString
						.equals(ApplicationConstant.MARK_ON_MAP_ONE)) {
					Log.d("da goi mark on map one", "------------------------");
					Locate locate = LocateDetailsFragment.locate;
					locate.SHOW_INFOR_WINDOW = true;
					locate.markOnMap();
					locate.moveCamera();
				} else if (extraString
						.equals(ApplicationConstant.MARK_ON_MAP_MY_LOCATE)) {
					Log.d("da goi mark on map my locate",
							"------------------------");
					int position = getIntent().getIntExtra(
							ApplicationConstant.POSTION, -1);
					MyLocate myLocate = MyLocateFragment.listMyLocates
							.get(position);
					if (myLocate != null) {
						myLocate.markOnMap();
						myLocate.moveCamera();
					}
				} else if (extraString.trim().equals(
						ApplicationConstant.GET_DIRECTION_VALUE.trim())) {
					Log.d("da goi get directionss", "------------------------");
					Double la1 = intent.getExtras().getDouble(
							ApplicationConstant.LAT1);
					Double log1 = intent.getExtras().getDouble(
							ApplicationConstant.LOG1);
					String name1 = intent.getExtras().getString(
							ApplicationConstant.NAME1);
					Double la2 = intent.getExtras().getDouble(
							ApplicationConstant.LAT2);
					Double log2 = intent.getExtras().getDouble(
							ApplicationConstant.LOG2);
					String name2 = intent.getExtras().getString(
							ApplicationConstant.NAME2);
					LatLng latLng1 = new LatLng(la1, log1);
					LatLng latLng2 = new LatLng(la2, log2);
					ArrayList<LatLng> markerPoints = new ArrayList<LatLng>();
					markerPoints.add(latLng1);
					markerPoints.add(latLng2);

					// Creating MarkerOptions and move camera
					MyLocate myLocate1 = new MyLocate(name1, null, la1, log1);
					LatLng nowLatl = new LatLng(la1, log1);
					MyLocate myLocate2 = new MyLocate(name2, null, la2, log2);
					myLocate1.markOnMap();
					myLocate2.markOnMap();
					myLocate1.moveCamera();
					// Setting the position of the marker
					MarkerOptions options = new MarkerOptions();
					options.position(latLng1);

					/**
					 * For the start location, the color of marker is GREEN and
					 * for the end location, the color of marker is RED.
					 */
					if (markerPoints.size() == 1) {
						options.icon(BitmapDescriptorFactory
								.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
					} else if (markerPoints.size() == 2) {
						options.icon(BitmapDescriptorFactory
								.defaultMarker(BitmapDescriptorFactory.HUE_RED));
					}
					// Add new marker to the Google Map Android API V2
					// Checks, whether start and end locations are captured
					if (markerPoints.size() >= 2) {
						LatLng origin = markerPoints.get(0);
						LatLng dest = markerPoints.get(1);

						// Getting URL to the Google Directions API
						String url = getDirectionsUrl(origin, dest);

						DownloadTask downloadTask = new DownloadTask();

						// Start downloading json data from Google Directions
						// API
						downloadTask.execute(url);
					}
				} else {
					Log.d("k get dc", "------------------------");
				}

			}
			Log.d("ket thuc oncreate", "------------------------");
		}
		googleMap.setOnCameraChangeListener(new OnCameraChangeListener() {

			@Override
			public void onCameraChange(CameraPosition position) {
				// TODO Auto-generated method stub
				if (role_cal_cameraChange == true) {
					LatLngBounds.Builder builder = new LatLngBounds.Builder();

					if (ApplicationConstant.IS_CALLING_BOOKMARK == true
							|| ApplicationConstant.IS_CALLING_RECENT == true) {
						Log.d("Mapactivity mark some bookmark recent:",
								BookmarkRecentFragment.listLocate.size() + "");
						for (Locate locate : BookmarkRecentFragment.listLocate) {
							if (locate.getIsChecked()) {
								locate.markOnMap();
								builder.include(new LatLng(locate.getLa(),
										locate.getLog()));
							}
						}
					} else {
						Log.d("Mapactivity mark some OnCameraChangeListener:",
								LoadLocate.listLocate.size() + "");
						for (Locate locate : LoadLocate.listLocate) {
							locate.markOnMap();
							builder.include(new LatLng(locate.getLa(), locate
									.getLog()));
						}
					}
					LatLngBounds bounds = builder.build();
					int padding = 15; // offset from edges of the map in pixels
					CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(
							bounds, padding);
					googleMap.moveCamera(cu);
					googleMap.animateCamera(cu);
					role_cal_cameraChange = false;
				}
			}
		});

	}

	// get
	// direction--------------------------------------------------------------------------------------------------
	private String getDirectionsUrl(LatLng origin, LatLng dest) {

		// Origin of route
		String str_origin = "origin=" + origin.latitude + ","
				+ origin.longitude;

		// Destination of route
		String str_dest = "destination=" + dest.latitude + "," + dest.longitude;

		// Sensor enabled
		String sensor = "sensor=false";

		// Building the parameters to the web service
		String parameters = str_origin + "&" + str_dest + "&" + sensor;

		// Output format
		String output = "json";

		// Building the url to the web service
		String url = "https://maps.googleapis.com/maps/api/directions/"
				+ output + "?" + parameters;

		return url;
	}

	// Fetches data from url passed
	private class DownloadTask extends AsyncTask<String, Void, String> {
		@Override
		protected void onPreExecute() {
			// TODO Auto-generated method stub
			super.onPreExecute();
			progressDialog.show();
		}

		// Downloading data in non-ui thread
		@Override
		protected String doInBackground(String... url) {

			// For storing data from web service
			String data = "";

			try {
				// Fetching the data from web service
				data = downloadUrl(url[0]);
			} catch (Exception e) {
				Log.d("Background Task", e.toString());
			}
			return data;
		}

		// Executes in UI thread, after the execution of
		// doInBackground()
		@Override
		protected void onPostExecute(String result) {
			super.onPostExecute(result);

			ParserTaskDirection parserTask = new ParserTaskDirection();
			// Invokes the thread for parsing the JSON data
			parserTask.execute(result);
			Log.d("----------------------url service:", result);

		}
	}

	/** A method to download json data from url */
	private String downloadUrlPace(String strUrl) throws IOException {
		String data = "";
		InputStream iStream = null;
		HttpURLConnection urlConnection = null;
		try {
			URL url = new URL(strUrl);

			// Creating an http connection to communicate with url
			urlConnection = (HttpURLConnection) url.openConnection();

			// Connecting to url
			urlConnection.connect();

			// Reading data from url
			iStream = urlConnection.getInputStream();

			BufferedReader br = new BufferedReader(new InputStreamReader(
					iStream));

			StringBuffer sb = new StringBuffer();

			String line = "";
			while ((line = br.readLine()) != null) {
				sb.append(line);
			}

			data = sb.toString();

			br.close();

		} catch (Exception e) {
			Log.d("Exception while downloading url", e.toString());
		} finally {
			iStream.close();
			urlConnection.disconnect();
		}
		return data;
	}

	/** A class to parse the Google Places in JSON format */
	private class ParserTaskDirection extends

	AsyncTask<String, Integer, List<List<HashMap<String, String>>>> {

		// Parsing the data in non-ui thread
		@Override
		protected List<List<HashMap<String, String>>> doInBackground(
				String... jsonData) {

			JSONObject jObject;
			List<List<HashMap<String, String>>> routes = null;

			try {
				jObject = new JSONObject(jsonData[0]);
				Log.d("----------------jsondata", jsonData[0]);
				dao.DirectionsJSONParser parser = new dao.DirectionsJSONParser();

				// Starts parsing data
				routes = parser.parse(jObject);
			} catch (Exception e) {
				e.printStackTrace();
			}
			return routes;
		}

		// Executes in UI thread, after the parsing process
		@Override
		protected void onPostExecute(List<List<HashMap<String, String>>> result) {
			ArrayList<LatLng> points = null;
			PolylineOptions lineOptions = null;
			MarkerOptions markerOptions = new MarkerOptions();
			String distance = "";
			String duration = "";

			if (result.size() < 1) {
				Toast.makeText(getBaseContext(), "No Points",
						Toast.LENGTH_SHORT).show();
				return;
			}

			// Traversing through all the routes
			for (int i = 0; i < result.size(); i++) {
				points = new ArrayList<LatLng>();
				lineOptions = new PolylineOptions();

				// Fetching i-th route
				List<HashMap<String, String>> path = result.get(i);
				Log.d("@@@@@@@@@@@list hash map", "" + i);
				// Fetching all the points in i-th route
				for (int j = 0; j < path.size(); j++) {
					HashMap<String, String> point = path.get(j);
					Log.d("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@hashmap",
							"" + i);
					for (String s : point.keySet()) {
						Log.d("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@hasmap key:",
								s);
					}
					if (j == 0) { // Get distance from the list
						distance = point.get("distance");
						continue;
					} else if (j == 1) { // Get duration from the list
						duration = point.get("duration");
						continue;
					}

					double lat = Double.parseDouble(point.get("lat"));
					double lng = Double.parseDouble(point.get("lng"));
					LatLng position = new LatLng(lat, lng);

					points.add(position);
				}
				Log.d("@@@@@@@@@Point num:", "" + points.size());
				lineOptions.addAll(points);
				lineOptions.width(4);
				lineOptions.color(Color.parseColor("#C6C4FF"));

			}
			// Drawing polyline in the Google Map for the i-th route
			googleMap.addPolyline(lineOptions);
			if (progressDialog != null && progressDialog.isShowing())
				progressDialog.dismiss();
		}
	}

	/** A method to download json data from url */
	private String downloadUrl(String strUrl) throws IOException {
		String data = "";
		InputStream iStream = null;
		HttpURLConnection urlConnection = null;
		try {
			URL url = new URL(strUrl);

			// Creating an http connection to communicate with url
			urlConnection = (HttpURLConnection) url.openConnection();

			// Connecting to url
			urlConnection.connect();

			// Reading data from url
			iStream = urlConnection.getInputStream();

			BufferedReader br = new BufferedReader(new InputStreamReader(
					iStream));

			StringBuffer sb = new StringBuffer();

			String line = "";
			while ((line = br.readLine()) != null) {
				sb.append(line);
			}

			data = sb.toString();

			br.close();

		} catch (Exception e) {
			Log.d("Exception while downloading url", e.toString());
		} finally {
			iStream.close();
			urlConnection.disconnect();
		}
		return data;
	}

	/*
	 * ----------------Fetches all places from GooglePlaces AutoComplete Web
	 * Service------------
	 * ------------------------------------------------------
	 * -----------------------------------
	 */
	private class PlacesTask extends AsyncTask<String, Void, String> {

		@Override
		protected String doInBackground(String... place) {
			// For storing data from web service
			String data = "";

			// Obtain browser key from https://code.google.com/apis/console
			String key = "key=AIzaSyAh2TPdR9LPSqkBApPGEW02WPQBhJG2GJ0";

			String input = "";

			try {
				input = "input=" + URLEncoder.encode(place[0], "utf-8");
			} catch (UnsupportedEncodingException e1) {
				e1.printStackTrace();
			}

			// place type to be searched
			String types = "types=geocode";

			// Sensor enabled
			String sensor = "sensor=false";

			// Building the parameters to the web service
			String parameters = input + "&" + types + "&" + sensor + "&" + key;

			// Output format
			String output = "json";

			// Building the url to the web service
			String url = "https://maps.googleapis.com/maps/api/place/autocomplete/"
					+ output + "?" + parameters;

			try {
				// Fetching the data from we service
				data = downloadUrl(url);
				Log.d("thoainguyen", url);
				Log.d("---thoainguyen PlacesTask data:", data);
			} catch (Exception e) {
				Log.d("Background Task", e.toString());
			}
			return data;
		}

		@Override
		protected void onPostExecute(String result) {
			super.onPostExecute(result);

			// Creating ParserTask
			parserTask = new ParserTaskPlace();

			// Starting Parsing the JSON string returned by Web Service
			parserTask.execute(result);
		}
	}

	/** A class to parse the Google Places in JSON format */
	private class ParserTaskPlace extends
			AsyncTask<String, Integer, List<HashMap<String, String>>> {

		JSONObject jObject;

		@Override
		protected List<HashMap<String, String>> doInBackground(
				String... jsonData) {

			List<HashMap<String, String>> places = null;

			PlaceJSONParser placeJsonParser = new PlaceJSONParser();

			try {
				jObject = new JSONObject(jsonData[0]);

				// Getting the parsed data as a List construct
				places = placeJsonParser.parse(jObject);

			} catch (Exception e) {
				Log.d("Exception", e.toString());
			}
			return places;
		}

		@Override
		protected void onPostExecute(List<HashMap<String, String>> result) {

			String[] from = new String[] { "description" };
			int[] to = new int[] { android.R.id.text1 };

			// Creating a SimpleAdapter for the AutoCompleteTextView
			SimpleAdapter adapter = new SimpleAdapter(getBaseContext(), result,
					android.R.layout.simple_list_item_1, from, to);

			// Setting the adapter
			atvPlaces.setAdapter(adapter);
		}
	}

	// geocoder task search place
	// -----------------------------------------------------------------------------------
	public class GeocoderTask extends AsyncTask<String, Void, List<Address>> {
		private LatLng latLng;

		@Override
		protected List<Address> doInBackground(String... arg0) {
			// TODO Auto-generated method stub
			Geocoder geocoder = new Geocoder(getBaseContext());
			List<Address> list = null;
			try {
				// get list address from arg0
				list = geocoder.getFromLocationName(arg0[0], 1);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return list;
		}

		@Override
		protected void onPostExecute(List<Address> result) {
			// TODO Auto-generated method stub
			if (result == null)
				Log.d("NULL", "----------");
			else
				Log.d("size:", String.valueOf(result.size()));
			super.onPostExecute(result);
			if (result != null) {
				googleMap.clear();
				for (int i = 0; i < result.size(); i++) {
					Address adr = result.get(i);
					// get information from address
					String addressText = null;
					Log.d("address:", adr.getAddressLine(0));
					// mark on map
					latLng = new LatLng(adr.getLatitude(), adr.getLongitude());

					if (i == 0) {
						// gan vi tri hien tai
						//nowLatl = latLng;
						addressText = adr.getAddressLine(0) + ", "
								+ adr.getAddressLine(1) + ", "
								+ adr.getAddressLine(2);
						MarkerOptions markerOptions = new MarkerOptions();
						markerOptions.position(latLng);
						markerOptions.title(addressText);
						markerOptions.icon(BitmapDescriptorFactory
								.fromResource(R.drawable.marker_ic));
						googleMap.addMarker(markerOptions).showInfoWindow();
						googleMap.moveCamera(CameraUpdateFactory
								.newLatLng(latLng));
						//txtAddress.setText(addressText);
						// gan flag bang false de onLocation khong bi goi
					}
				}
			} else
				Toast.makeText(getApplicationContext(), addressNotFound,
						Toast.LENGTH_LONG).show();
		}

	}
}
